package com.felix.spider.utils;

import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.javascript.JavaScriptEngine;
import com.gargoylesoftware.htmlunit.javascript.JavaScriptErrorListener;
import com.gargoylesoftware.htmlunit.javascript.host.Window;

import java.util.logging.LogManager;

/**
 * @author 作者: 马子超
 * @version 创建时间：2017年6月27日 上午11:45:49 @Description: TODO(HtmlUnit的动态WebClient初始化)
 * @Package: htmlunitTest @Title: WebClientutils.java
 */
public class HtmlUnitUtils {

    private static WebClient client;

    public static synchronized WebClient getClient() {
        LogManager.getLogManager().reset();
        if (client == null) {
            client = new WebClient(BrowserVersion.getDefault());
            client.setJavaScriptTimeout(30000);
            client.setAjaxController(new NicelyResynchronizingAjaxController());
            client.setJavaScriptEngine(new MyJavaScriptEngine(client));
            client.getOptions().setJavaScriptEnabled(true); // 默认执行js，如果不执行js，则可能会登录失败，因为用户名密码框需要js来绘制。
            client.getOptions().setCssEnabled(false);
            client.getOptions().setRedirectEnabled(true);
            client.getOptions().setTimeout(60000);
            client.getOptions().setThrowExceptionOnScriptError(false);
            client.getOptions().setThrowExceptionOnFailingStatusCode(false);
            client.getOptions().setUseInsecureSSL(true);
        }
        return client;
    }

    public static synchronized void close() {
        if (client != null) client.close();
    }

    /**
     * @author 作者: 马子超
     * @version 创建时间：2017年6月27日 下午11:14:23 @Description: TODO(自定义的不显示js解析器 为了不显示js错误)
     * @Package: htmlunitTest @Title: WebClientutils.java
     */
    static class MyJavaScriptEngine extends JavaScriptEngine {

        public MyJavaScriptEngine(WebClient webClient) {
            super(webClient);
        }

        @Override
        protected void handleJavaScriptException(
                final ScriptException scriptException, final boolean triggerOnError) {
            // Trigger window.onerror, if it has been set.
            final HtmlPage page = scriptException.getPage();
            if (triggerOnError && page != null) {
                final WebWindow window = page.getEnclosingWindow();
                if (window != null) {
                    final Window w = (Window) window.getScriptableObject();
                    if (w != null) {
                        try {
                            w.triggerOnError(scriptException);
                        } catch (final Exception e) {
                            handleJavaScriptException(new ScriptException(page, e, null), false);
                        }
                    }
                }
            }
            final JavaScriptErrorListener javaScriptErrorListener =
                    getWebClient().getJavaScriptErrorListener();
            if (javaScriptErrorListener != null) {
                javaScriptErrorListener.scriptException(page, scriptException);
            }
            // Throw a Java exception if the user wants us to.
            if (getWebClient().getOptions().isThrowExceptionOnScriptError()) {
                throw scriptException;
            }
            /** 关键点，注释了最后打印日志 */
            // Log the error; ScriptException instances provide good debug info.
            // LOG.info("Caught script exception", scriptException);
        }
    }
}
